package com.frp.lib.client;

import com.frp.lib.config.ProxyModel;
import io.netty.channel.Channel;

import java.util.HashMap;
import java.util.Map;

/**
 * Created by hujianjun on 11/23 0023.
 */
public interface Proxy {
    void run();
    void inWorkConn(Object object);
    void close();
    void setControl(ClientControl cc);
    void setProxyDefine(ProxyModel.ProxyDefine proxyDefine);
    ProxyModel.ProxyDefine getProxyDefine();

    void addChannelMap(Channel remote, Channel local);
    void removeChannelMap(Channel remote);


    class BaseProxy implements Proxy {
        public static Map<String, Class<? extends Proxy>> ProxyMap = new HashMap<String, Class<? extends Proxy>>();
        static {
            ProxyMap.put("tcp", TcpProxy.class);
            ProxyMap.put("http", HttpProxy.class);
        }
        public ClientControl control;
        public ProxyModel.ProxyDefine proxyDefine;
        // serverChannel <-> clientChannel
        Map<Channel, Channel> channelMap = new HashMap<Channel, Channel>();
        static Proxy create(ClientControl cc, ProxyModel.ProxyDefine proxyDefine) {
            String type = proxyDefine.getType();
            Class<? extends Proxy> clazz = ProxyMap.get(type);
            if (null == clazz) {
                throw new RuntimeException("can not find proxy type " + type);
            }
            try {
                Proxy proxy = clazz.newInstance();
                proxy.setControl(cc);
                proxy.setProxyDefine(proxyDefine);
                return proxy;
            } catch (InstantiationException e) {
                throw new RuntimeException("new instance error.", e);
            } catch (IllegalAccessException e) {
                throw new RuntimeException("new instance error.", e);
            }
        }

        public void run() {

        }

        public void inWorkConn(Object object) {
//            System.out.println("in work conn.");

        }

        public void close() {

        }

        public void setControl(ClientControl cc) {
            this.control = cc;
        }

        public void setProxyDefine(ProxyModel.ProxyDefine proxyDefine) {
            this.proxyDefine = proxyDefine;
        }

        @Override
        public ProxyModel.ProxyDefine getProxyDefine() {
            return this.proxyDefine;
        }

        @Override
        public void addChannelMap(Channel remote, Channel local) {
            this.channelMap.put(remote, local);
        }

        @Override
        public void removeChannelMap(Channel remote) {
            this.channelMap.remove(remote);
        }
    }

    class TcpProxy extends BaseProxy {
        @Override
        public void inWorkConn(Object object) {
            //todo will connect and join

        }
    }

    class HttpProxy extends BaseProxy {

    }
}
